package com.iqiyi.pps.epg.core.service.notifymail;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iqiyi.pps.epg.core.async.AsyncService;
import com.iqiyi.pps.epg.core.async.HeartBeatCenter;
import com.iqiyi.pps.epg.core.async.IAsyncTask;
import com.iqiyi.pps.epg.core.async.IHeartBeat;
import com.iqiyi.pps.epg.core.model.channel.ChannelConfig;
import com.iqiyi.pps.epg.core.model.task.SimpleTask;
import com.iqiyi.pps.epg.core.model.task.SimpleTaskStatus;
import com.iqiyi.pps.epg.core.model.task.SimpleTaskType;
import com.iqiyi.pps.epg.core.service.channel.ChannelService;
import com.iqiyi.pps.epg.core.service.program.ProgramService;
import com.iqiyi.pps.epg.core.service.task.SimpleTaskService;
import com.iqiyi.pps.epg.core.utils.*;
import com.iqiyi.pps.epg.core.utils.mail.MailConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.*;

/**
 * Created by karkarrotxu on 2015/12/15.
 */
@Lazy(false)
@Service
public class NotifyMailServiceImpl extends AsyncService implements InitializingBean, NotifyMailService, IHeartBeat {
    private final static int HEARTBEAT_DELAY = 60 * 1000; //
    public static final String MSG_STREAM_DELAY = "流延迟,需要校对节目开始时间";
    public static final String MSG_STREAM_INTERRUPT = "本场直播流有中断";
    private long heartBeatTime = 0;
    @Autowired
    private SimpleTaskService simpleTaskService;
    @Autowired
    private ChannelService channelService;

    @Autowired
    private ProgramService programService;


    private static final Logger logger = LoggerFactory.getLogger(NotifyMailServiceImpl.class);

    public void afterPropertiesSet() throws Exception {
        logger.info("NofityMailServiceImpl afterPropertiesSet");
        HeartBeatCenter.add(this);
    }

    protected boolean queryEnable(){
        return getEnable("mail");
    }

    @Override
    public void addMailAsyncTask(int tosType, int mailType, Map<String, String> map) {
        logger.info("[addMailAsyncTask]  start");
        JSONObject taskJOSON = new JSONObject();
        taskJOSON.put(MailConstant.MAIL_TYPE, mailType);
        taskJOSON.put(MailConstant.TOS_TYPE, tosType);
        taskJOSON.put(MailConstant.PARAMS, map);
        SimpleTask simpleTask = new SimpleTask();
        simpleTask.setServerIp(RequestUtils.getLoadlIpByOS());
        simpleTask.setWorkIp(simpleTask.getServerIp());
        simpleTask.setTaskStatus(SimpleTaskStatus.WAIT.getStatusIndex());
        simpleTask.setTaskType(SimpleTaskType.NOTIFY_MAIL.getTypeIndex());
        simpleTask.setCreateTime(new Timestamp(System.currentTimeMillis()));
        simpleTask.setExpireTime(new Timestamp(System.currentTimeMillis() + DateTimeUtil.DAY_TIME));
        simpleTask.setParams(taskJOSON.toJSONString());
        simpleTaskService.saveTask(simpleTask);
        logger.info("[addMailAsyncTask]  end id:{}", simpleTask.getId());
        this.accept(new IAsyncTask() {
            @Override
            public void doTask() {
                executeSimpleTaskList();
            }
        });
    }

    public void addStreamMsgAsyncTask(boolean changeToRun, Map<String, String> map) {
        final StringBuffer content = new StringBuffer();
        content.append(map.get(MailConstant.P_START_TIME) + "~" + map.get(MailConstant.P_STOP_TIME));
        content.append("《" + map.get(MailConstant.P_NAME) + "》 异常:");
        content.append(changeToRun ? MSG_STREAM_DELAY : MSG_STREAM_INTERRUPT);
        final String qpId = map.get(MailConstant.P_QIPU_ID) ;
        final String eventTime = map.get("eventTime") ;
        this.accept(new IAsyncTask() {
            @Override
            public void doTask() {
                logger.info("[addStreamMsgAsyncTask]start sendMsg qpId={},eventTime={}",qpId,eventTime);
                SendMsgUtils.sendMsg(getMsgToList(), content.toString(), "【epg】", "warn");
            }
        });
    }

    private String getMsgToList() {
        List<ChannelConfig> configs = channelService.getConfig(ChannelConfig.STREAM_SPAN_MSG_GROUP);
        StringBuffer sb = new StringBuffer();
        int size = configs.size();
        for (int i = 0; i < size; i++) {
            if (i > 0) {
                sb.append(",");
            }
            sb.append(configs.get(i).getVal());
        }

        return sb.toString();
    }

    private void executeSimpleTask(SimpleTask simpleTask) {
        logger.info("[executeSimpleTask] execute:{}", simpleTask.getId());
        try {
            long startTime = System.currentTimeMillis();
            JSONObject notifyMail = JSON.parseObject(simpleTask.getParams());
            MailContentUtil.ContentType contentType = MailContentUtil.ContentType.getTypeByIndex(notifyMail.getIntValue(MailConstant.MAIL_TYPE));
            Map<String, String> map = JSON.toJavaObject(notifyMail.getJSONObject(MailConstant.PARAMS), Map.class);
            String channelName = map.get(MailConstant.C_NAME);

            String[] tos = null;
            if (notifyMail.getIntValue(MailConstant.TOS_TYPE) == 0) {
                String assigned = map.get(MailConstant.ASSIGN_TOS);
                if (assigned == null || assigned.isEmpty()) {
                    tos = new String[0];
                } else {
                    tos = assigned.trim().split(",");
                }
            } else {
                long channelId = 0;
                if (map.get(MailConstant.C_ID) != null) {
                    channelId = Long.valueOf(map.get(MailConstant.C_ID));
                    map.remove(MailConstant.C_ID);
                }
                long programId = 0;
                if (map.get(MailConstant.P_ID) != null) {
                    programId = Long.valueOf(map.get(MailConstant.P_ID));
                    map.remove(MailConstant.P_ID);
                }
                tos = getTos(channelId, programId, notifyMail.getIntValue(MailConstant.TOS_TYPE));
            }
            if (tos.length == 0) {
                logger.error("[executeSimpleTask][simpleTaskId={}] tos empty", simpleTask.getId());
                return;
            }
            String title = null;
            if (map.containsKey(MailConstant.ASSIGN_TITLE)) {
                title = map.get(MailConstant.ASSIGN_TITLE);
            } else {
                String titlePlus = map.get(MailConstant.TITLE_PLUS);
                if (null == titlePlus) {
                    titlePlus = "";
                } else {
                    map.remove(MailConstant.TITLE_PLUS);
                }
                title = String.format(MailContentUtil.getTitleTemplate(contentType), channelName) + titlePlus;
            }


            String content = MailContentUtil.getContent(contentType, map);
            boolean flag = SendMailUtils.sendMail(title, tos, content);
            long endTime = System.currentTimeMillis();
            if (flag) {
                simpleTask.setTaskStatus(SimpleTaskStatus.COMPLETE.getStatusIndex());
                simpleTask.setCompleteTime(new Timestamp(System.currentTimeMillis()));
                simpleTaskService.saveTask(simpleTask);
            }
            logger.info("[simpleTaskId={}] [costTime={}][flag={}]", simpleTask.getId(), (endTime - startTime), flag);
        } catch (Exception e) {
            logger.error("[exception={}] taskId:" + simpleTask.getId(), e);
        }
    }


    public String[] getTos(long channelId, long programId, int findType) {
        String[] retValue = null;
        Set<String> sendSet = new HashSet<String>();
        switch (findType) {
            case MailConstant.TOS_TYPE_FROM_LOG:
            case MailConstant.TOS_TYPE_LS_REMIND:
            case MailConstant.TOS_TYPE_LS_CHECK_LIST:
            case MailConstant.TOS_TYPE_P_MAIL_TYPE:
            case MailConstant.TOS_TYPE_LS_ADD_NOTIFY:
            case MailConstant.TOS_TYPE_EPG_TEAM:
            case MailConstant.TOS_TYPE_DAOJU_MAIL_GROUP:
            case MailConstant.TOS_TYPE_STREAM_ERROR_GROUP:
            case MailConstant.TOS_TYPE_STREAM_SPAN_MSG_GROUP:
            case MailConstant.TOS_TYPE_FROM_STREAM_LOG:
            case MailConstant.TOS_TYPE_DAILYCHECK_MAIL_TYPE:
            case MailConstant.TOS_TYPE_FROM_CAROUSEL_LOG:
                sendSet.addAll(searchByMode(findType, channelId, programId));
                break;
            default:
                int start = 1;
                while (findType >= start) {
                    if ((findType & start) == start) {
                        sendSet.addAll(searchByMode(start, channelId, programId));
                    }
                    start = start << 1;
                }
                break;
        }
        retValue = sendSet.toArray(new String[0]);
        return retValue;
    }

    private List<String> searchByMode(int searchMode, long channelId, long programId) {
        switch (searchMode) {
            case MailConstant.TOS_TYPE_FROM_LOG:
                List<String> userList = new ArrayList<String>();
                if (channelId > 0) {
                    userList.addAll(channelService.searchForLogUser(channelId));
                }
                if (programId > 0) {
                    userList.addAll(programService.searchForLogUser(programId));
                }
                return userList;
            case MailConstant.TOS_TYPE_LS_REMIND:
                return channelService.searchForUser("ls_start_remind");
            case MailConstant.TOS_TYPE_LS_CHECK_LIST:
                return channelService.searchForUser("ls_check_list");
            case MailConstant.TOS_TYPE_P_MAIL_TYPE:
                return channelService.searchForUser("PMailType");
            case MailConstant.TOS_TYPE_LS_ADD_NOTIFY:
                return channelService.searchForUser("ls_add_notify");
            case MailConstant.TOS_TYPE_EPG_TEAM:
                return channelService.searchForUser("EPG_TEAM");
            case MailConstant.TOS_TYPE_DAOJU_MAIL_GROUP:
                return channelService.searchForUser(ChannelConfig.DAOJU_MAIL_GROUP);
            case MailConstant.TOS_TYPE_STREAM_ERROR_GROUP:
                return channelService.searchForUser(ChannelConfig.STREAM_ERROR_GROUP);
            case MailConstant.TOS_TYPE_STREAM_SPAN_MSG_GROUP:
                return channelService.searchForUser(ChannelConfig.STREAM_SPAN_MSG_GROUP);
            case MailConstant.TOS_TYPE_FROM_STREAM_LOG:
                return channelService.searchForStreamErrorLogUser(channelId);
            case MailConstant.TOS_TYPE_FROM_CAROUSEL_LOG:
                return channelService.searchForCarouselLogUser(channelId);
            case MailConstant.TOS_TYPE_DAILYCHECK_MAIL_TYPE:
                return channelService.searchForUser("DCMailType");
            default:
                break;
        }
        return new ArrayList<String>();
    }

    private void executeSimpleTaskList() {
        logger.info("[executeSimpleTaskList] execute");
        try {

            List<SimpleTask> resultList = simpleTaskService.findList(SimpleTaskType.NOTIFY_MAIL.getTypeIndex(), SimpleTaskStatus.WAIT.getStatusIndex());
            if (resultList == null || resultList.size() == 0) {
                logger.info("[result empty] resultList == null :" + (resultList == null));
                return;
            }
            logger.info("[executeSimpleTaskList] execute size:" + resultList);
            long currentTime = System.currentTimeMillis();
            List<SimpleTask> updateList = new ArrayList<SimpleTask>(2048);
            for (SimpleTask simpleTask : resultList) {
                if (currentTime <= simpleTask.getExpireTime().getTime()) {
                    executeSimpleTask(simpleTask);
                } else {
                    simpleTask.setTaskStatus(SimpleTaskStatus.EXPIRED.getStatusIndex());
                    updateList.add(simpleTask);
                }
            }
            logger.info("[executeSimpleTaskList] overtime size:" + updateList);
            simpleTaskService.batchUpdateList(updateList);

        } catch (Exception e) {
            logger.error("[executeSimpleTaskList] error", e);
        }
        logger.info("[executeSimpleTaskList] execute end");
    }

    @Override
    public void tick(long now) {
        if (now - heartBeatTime >= HEARTBEAT_DELAY) {
            heartBeatTime = now;
            logger.info("NotifyMailServiceImpl tick");
            this.accept(new IAsyncTask() {
                @Override
                public void doTask() {
                    executeSimpleTaskList();
                }
            });
        }
    }
}
